﻿using HDSmartCommunity.BUS;
using HDSmartCommunity.DAL;
using HDSmartCommunity.Models;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace HDSmartCommunity.DevicePlatform
{
    public class RaspberryPie
    {
        public bool SetNtp(string ipAddress)
        {
            try
            {
                RunCommand("chmod 777 /etc/ntp.conf");
                using (FileStream fs = new FileStream("/etc/ntp.conf", FileMode.Open, FileAccess.Write))
                {
                    StreamWriter sw = new StreamWriter(fs);
                    sw.BaseStream.Seek(0, SeekOrigin.Current);
                    sw.WriteLine(string.Format("server {0} prefer", ipAddress));
                    sw.Flush();
                    sw.Close();
                    fs.Close();
                }
                DeviceDAL da = new DeviceDAL();
                da.UpdatNtpServer(ipAddress);

                //RunCommand("reboot");
                return true;
            }
            catch (Exception e)
            {
                LogHelper.Log(e.ToString());
                return false;
            }
        }

        public void RunCommand(string command)
        {
            Process.Start("sudo", command);
        }

        public NetInfo GetJMNetInfo()
        {
            NetInfo netInfo = new NetInfo();
            try
            {
                StreamReader reader = new StreamReader(@"/etc/netplan/01-network-manager-all.yaml", Encoding.Default);
                string theReply = reader.ReadToEnd();
                reader.Close();
                Regex strRegex = new Regex(@"(?<str>([^\w\s]+|\s*)enp1s0:\s*dhcp4: no([\w\W]*))");
                Regex addressRegex = new Regex(@"([^\w\s]+|\s*)addresses:\s*[^\w\s](?<address>\d+.\d+.\d+.\d+/\d+)]\s*");
                Regex gatewayRegex = new Regex(@"(?<gateway>([^\w\s]+|\s*)via:\s*\d+.\d+.\d+.\d+)\s*");
                Regex maskReg = new Regex(@"\d+.\d+.\d+.\d+/(?<mask>\d+)\s*");
                Regex ipRegex = new Regex(@"\s*(?<ip>\d+.\d+.\d+.\d+)\s*");

                MatchCollection strCollection = strRegex.Matches(theReply);

                if (strCollection.Count > 0)
                {
                    string str_value = strCollection[0].Groups["str"].Value;
                    MatchCollection addressCollection = addressRegex.Matches(str_value);
                    MatchCollection routerCollection = gatewayRegex.Matches(str_value);
                    for (int i = 0; i < addressCollection.Count; i++)
                    {
                        string str = addressCollection[i].Groups["address"].Value.Trim();
                        string ip = ipRegex.Matches(str)[0].Groups["ip"].Value.Trim();
                        netInfo.IP = ip;
                        int mask = Convert.ToInt32(maskReg.Matches(str)[0].Groups["mask"].Value.Trim());
                        string Mask = GetMask(mask);
                        netInfo.Mask = Mask;
                    }

                    for (int i = 0; i < routerCollection.Count; i++)
                    {
                        string str = routerCollection[i].Groups["gateway"].Value.Trim();
                        string ip = ipRegex.Matches(str)[0].Groups["ip"].Value.Trim();
                        netInfo.Router = ip;
                    }
                }

                return netInfo;
            }
            catch (Exception ex)
            {
                LogHelper.Log(ex.ToString());
                return netInfo;
            }
        }

        public List<Line18NetInfo> GetLine18NetInfo(int networknum)
        {
            List<Line18NetInfo> line18NetInfos = new List<Line18NetInfo>();
            try
            {
                StreamReader reader = new StreamReader(@"/etc/netplan/01-network-manager-all.yaml", Encoding.Default);
                string theReply = reader.ReadToEnd();
                reader.Close();
                for (int k = 1; k < networknum + 1; k++)
                {
                    Line18NetInfo line18NetInfo = new Line18NetInfo();
                    line18NetInfo.ID = k;
                    Regex strRegex = new Regex(string.Format(@"(?<str>([^\w\s]+|\s*)enp{0}s0:\s*dhcp4: no([\w\W]*))", k));
                    Regex addressRegex = new Regex(@"([^\w\s]+|\s*)addresses:\s*[^\w\s](?<address>\d+.\d+.\d+.\d+/\d+)]\s*");
                    Regex gatewayRegex = new Regex(@"([^\w\s]+|\s*)gateway4:\s*(?<gateway>\d+.\d+.\d+.\d+)\s*");
                    Regex maskReg = new Regex(@"\d+.\d+.\d+.\d+/(?<mask>\d+)\s*");
                    Regex ipRegex = new Regex(@"\s*(?<ip>\d+.\d+.\d+.\d+)\s*");
                    Regex routesRegex = new Regex(@"(?<routes>([^\w\s]+|\s*)routes:([\w\W]*))");
                    Regex routes_addressRegex = new Regex(@"([^\w\s]+|\s*)-\s*to:\s*(?<routeaddress>\d+.\d+.\d+.\d+/\d+)\s*");
                    Regex routes_gatewayRegex = new Regex(@"([^\w\s]+|\s*)via:\s*(?<via>\d+.\d+.\d+.\d+)\s*");
                    MatchCollection strCollection = strRegex.Matches(theReply);

                    if (strCollection.Count > 0)
                    {
                        string str_value = strCollection[0].Groups["str"].Value;
                        MatchCollection addressCollection = addressRegex.Matches(str_value);
                        MatchCollection gatewayCollection = gatewayRegex.Matches(str_value);
                        MatchCollection routesCollection = routesRegex.Matches(str_value);
                        if (addressCollection.Count > 0)
                        {
                            string str = addressCollection[0].Groups["address"].Value.Trim();
                            string ip = ipRegex.Matches(str)[0].Groups["ip"].Value.Trim();
                            line18NetInfo.IP = ip;
                            int mask = Convert.ToInt32(maskReg.Matches(str)[0].Groups["mask"].Value.Trim());
                            string Mask = GetMask(mask);
                            line18NetInfo.Mask = Mask;

                            if (gatewayCollection.Count > 0)
                            {
                                string str_4 = gatewayCollection[0].Groups["gateway"].Value.Trim();
                                string ip_4 = ipRegex.Matches(str_4)[0].Groups["ip"].Value.Trim();
                                line18NetInfo.GateWay = ip_4;
                            }
                            else
                            {
                                line18NetInfo.GateWay = "";
                            }

                            MatchCollection routesstrCollection = routesRegex.Matches(str_value);
                            if (routesstrCollection.Count > 0)
                            {
                                string routestr_value = routesstrCollection[0].Groups["routes"].Value;
                                MatchCollection route_addressCollection = routes_addressRegex.Matches(routestr_value);
                                MatchCollection route_gatewayCollection = routes_gatewayRegex.Matches(routestr_value);

                                if (route_addressCollection.Count > 0)
                                {
                                    string str_3 = route_addressCollection[0].Groups["routeaddress"].Value.Trim();
                                    string ip_3 = ipRegex.Matches(str_3)[0].Groups["ip"].Value.Trim();
                                    line18NetInfo.RouteIP = ip_3;
                                    int mask_3 = Convert.ToInt32(maskReg.Matches(str)[0].Groups["mask"].Value.Trim());
                                    string Mask_3 = GetMask(mask);
                                    line18NetInfo.RouteMask = Mask_3;
                                }
                                else
                                {
                                    line18NetInfo.RouteIP = "";
                                    line18NetInfo.RouteMask = "";
                                }

                                if (route_gatewayCollection.Count > 0)
                                {
                                    string str_2 = route_gatewayCollection[0].Groups["via"].Value.Trim();
                                    string ip_2 = ipRegex.Matches(str_2)[0].Groups["ip"].Value.Trim();
                                    line18NetInfo.RouteGateWay = ip_2;
                                }
                                else
                                {
                                    line18NetInfo.RouteGateWay = "";
                                }
                            }
                        }
                        else
                        {
                            line18NetInfo.IP = "";
                            line18NetInfo.Mask = "";
                        }

                        
                    }
                    line18NetInfos.Add(line18NetInfo);
                }


                return line18NetInfos;
            }
            catch (Exception ex)
            {
                LogHelper.Log(ex.ToString());
                return line18NetInfos;
            }
        }

        public string GetMask(int value)
        {
            try
            {
                string str = string.Empty;
                for (int i = 0; i < value; i++)
                {
                    str += "1";
                }
                str = str.PadRight(32, '0');
                string a = Convert.ToInt32(str.Substring(0, 8), 2).ToString() + "." + Convert.ToInt32(str.Substring(8, 8), 2).ToString() + "." + Convert.ToInt32(str.Substring(16, 8), 2).ToString() + "." + Convert.ToInt32(str.Substring(24, 8), 2).ToString();
                return a;
            }
            catch
            {
                return "0.0.0.0";
            }
        }

        public bool UpdateJMNetInfo(NetInfo netInfo)
        {
            try
            {
                RunCommand("chmod 777 /etc/netplan/01-network-manager-all.yaml");
                using (FileStream fileStream = new FileStream("/etc/netplan/01-network-manager-all.yaml", FileMode.Open, FileAccess.Write, FileShare.Write))
                {
                    fileStream.Seek(0, SeekOrigin.Begin);
                    fileStream.SetLength(0);
                    using (StreamWriter streamWriter = new StreamWriter(fileStream))
                    {
                        streamWriter.WriteLine("network:");
                        streamWriter.WriteLine("  version: 2");
                        streamWriter.WriteLine("  renderer: NetworkManager");
                        streamWriter.WriteLine("  ethernets:");
                        streamWriter.WriteLine("    enp2s0:");
                        streamWriter.WriteLine("      dhcp4: yes");
                        streamWriter.WriteLine("    enp1s0:");
                        streamWriter.WriteLine("      dhcp4: no");
                        streamWriter.WriteLine("      addresses: [" + netInfo.IP + "/" + netInfo.Mask + "]");
                        streamWriter.WriteLine("      routes:");
                        streamWriter.WriteLine("        - to: 0.0.0.0/0");
                        streamWriter.WriteLine("          via: " + netInfo.Router);
                        streamWriter.WriteLine("          metric: 150");
                        streamWriter.WriteLine("      optional: true");
                        fileStream.Flush();
                        streamWriter.Close();
                    }

                    fileStream.Close();
                }
                RunCommand("netplan apply");
                return true;
            }
            catch (Exception ex)
            {
                LogHelper.Log(ex.ToString());
                return false;
            }
        }

        public bool CalibrationTime(string time)
        {
            try
            {
                RunCommand("date -s \"" + time + "\"");
                return true;
            }
            catch
            {
                return false;
            }
        }

        public string GetNtpIp()
        {
            try
            {
                StreamReader reader = new StreamReader(@"/etc/ntp.conf", Encoding.Default);
                string theReply = reader.ReadToEnd();
                reader.Close();
                Regex addressRegex = new Regex(@"server\s*(?<ip>\d+.\d+.\d+.\d+)\s*prefer");

                MatchCollection addressCollection = addressRegex.Matches(theReply);
                string str = addressCollection[0].Groups["ip"].Value.Trim();

                return str;
            }
            catch
            {
                return "";
            }
        }

        public bool UpdateLine18NetInfo(Line18NetInfo netInfo, int networknum)
        {
            try
            {
                List<Line18NetInfo> line18NetInfos = new List<Line18NetInfo>();
                line18NetInfos = GetLine18NetInfo(networknum);

                RunCommand("chmod 777 /etc/netplan/01-network-manager-all.yaml");
                using (FileStream fileStream = new FileStream("/etc/netplan/01-network-manager-all.yaml", FileMode.Open, FileAccess.Write, FileShare.Write))
                {
                    fileStream.Seek(0, SeekOrigin.Begin);
                    fileStream.SetLength(0);
                    using (StreamWriter streamWriter = new StreamWriter(fileStream))
                    {
                        streamWriter.WriteLine("network:");
                        streamWriter.WriteLine("  version: 2");
                        streamWriter.WriteLine("  renderer: NetworkManager");
                        streamWriter.WriteLine("  ethernets:");
                        foreach (var item in line18NetInfos)
                        {
                            if (item.ID == netInfo.ID)
                            {
                                streamWriter.WriteLine("    enp" + netInfo.ID + "s0:");
                                streamWriter.WriteLine("      dhcp4: no");
                                streamWriter.WriteLine("      addresses: [" + netInfo.IP + "/" + MaskToInt(netInfo.Mask) + "]");
                                streamWriter.WriteLine("      gateway4: " + netInfo.GateWay);
                            }
                            else
                            {
                                if (string.IsNullOrEmpty(item.IP))
                                {
                                    streamWriter.WriteLine("    enp" + item.ID + "s0:");
                                    streamWriter.WriteLine("      dhcp4: yes");
                                }
                                else
                                {
                                    streamWriter.WriteLine("    enp" + item.ID + "s0:");
                                    streamWriter.WriteLine("      dhcp4: no");
                                    streamWriter.WriteLine("      addresses: [" + item.IP + "/" + MaskToInt(item.Mask) + "]");
                                    streamWriter.WriteLine("      gateway4: " + item.GateWay);
                                }
                            }
                        }

                        fileStream.Flush();
                        streamWriter.Close();
                    }

                    fileStream.Close();
                }
                RunCommand("netplan apply");
                return true;
            }
            catch (Exception ex)
            {
                LogHelper.Log(ex.ToString());
                return false;
            }
        }

        public string MaskToInt(string mask)
        {
            string value = string.Empty;
            string[] array = mask.Replace(" ", "").Split('.');
            for (int i = 0; i < array.Length; i++)
            {
                value += Convert.ToString(Convert.ToInt32(array[i]), 2);
            }
            value = value.PadRight(32, '0');

            string keyWord = "1";
            int index = 0;
            int count = 0;
            while ((index = value.IndexOf(keyWord, index)) != -1)
            {
                count++;
                index = index + keyWord.Length;
            }
            return count.ToString();
        }
    }
}
